Skip to content

perf: efficient IPC layer, bundle split, monaco workers offload#28

Merged
remcostoeten merged 11 commits intomasterfrom
feature/performance-optimizations
Jan 26, 2026
Merged

perf: efficient IPC layer, bundle split, monaco workers offload#28
remcostoeten merged 11 commits intomasterfrom
feature/performance-optimizations

Conversation

@remcostoeten
Copy link
Copy Markdown
Owner

@remcostoeten remcostoeten commented Jan 26, 2026

Summary by CodeRabbit

  • New Features

    • Automated desktop release workflow (Linux/Windows/macOS).
    • Monaco editor integration and build tooling visualization.
    • Smooth table transitions, optimistic updates, and resizable database sidebar.
    • New maintenance utilities for dependency and cleanup scanning.
  • Bug Fixes

    • Robust container sorting to handle missing names/states.
  • Improvements

    • Theme renamed from "haptic" to "night".
    • Removed several unused UI components and hooks to slim the app.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown

vercel bot commented Jan 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
dora Ready Ready Preview, Comment Jan 26, 2026 4:08am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 26, 2026

📝 Walkthrough

Walkthrough

Adds a GitHub Actions release workflow, refactors desktop app UI (many component removals), introduces Monaco worker initialization, replaces theme "haptic" with "night", adds optimistic updates for table cell mutations, injects a deps indirection for Tauri shell in docker client, and adds multiple developer tooling scripts and dependency updates.

Changes

Cohort / File(s) Summary
Release & CI
​.github/workflows/release.yml
New release workflow publishing desktop artifacts for Linux/Windows/macOS.
Tests & Test Setup
__tests__/setup/vitest.setup.ts, __tests__/apps/desktop/.../lsp-patterns.test.ts
Add jest-dom matchers; update test import paths.
Docker manager & tests
apps/desktop/src/features/docker-manager/api/docker-client.ts, __tests__/apps/desktop/src/features/docker-manager/api/docker-client.test.ts, __tests__/apps/desktop/src/features/docker-manager/api/container-service.test.ts, apps/desktop/src/features/docker-manager/components/docker-view.tsx, apps/desktop/src/features/docker-manager/hooks/*, apps/desktop/src/features/docker-manager/api/queries/use-container-sizes.ts
Introduce deps.getCommand() indirection for shell Command; update tests to use DI and dynamic imports; remove several docker-related hooks (useContainerSizes, useContainerHistory, useContainerSortFilter); make docker-view sorting null-safe; adapt tests to new shapes.
Theme / Appearance
apps/desktop/src/shared/lib/appearance-store.ts, apps/desktop/src/features/sidebar/components/appearance-panel.tsx, apps/desktop/src/features/sidebar/components/bottom-toolbar.tsx, apps/desktop/src/index.css
Replace theme value hapticnight across types, UI and CSS.
Sidebar & panels
apps/desktop/src/features/sidebar/components/nav-buttons.tsx, apps/desktop/src/features/sidebar/components/spotlight-trigger.tsx, apps/desktop/src/features/sidebar/components/theme-panel.tsx, apps/desktop/src/features/sidebar/components/sidebar-bottom-panel.tsx, apps/desktop/src/features/sidebar/database-sidebar.tsx
Remove NavButtons, SpotlightTrigger, ThemePanel; adjust SidebarBottomPanel sizing; add resizable database sidebar with drag handle and topPanelRatio.
SQL console UI removal
apps/desktop/src/features/sql-console/components/query-sidebar.tsx, apps/desktop/src/features/sql-console/components/schema-browser.tsx
Deleted QuerySidebar and SchemaBrowser components and related UI logic.
Database Studio & data-grid
apps/desktop/src/features/database-studio/database-studio.tsx, apps/desktop/src/features/database-studio/components/data-grid.tsx, apps/desktop/src/features/database-studio/utils/get-column-icon.tsx
Add table-transition caching and skeleton overlay; move no-columns check; remove getColumnIcon utility.
Data-provider / optimistic updates
apps/desktop/src/core/data-provider/hooks.ts
Implement optimistic updates for updateCell via onMutate/onError/onSettled, add placeholderData and adjusted cache timings.
Drizzle runner UI
apps/desktop/src/features/drizzle-runner/components/lsp-demo-widget.tsx
Add completion/success state, auto-close timer, and adjusted step/sequence flow and UI.
Tauri / DB backend
apps/desktop/src-tauri/src/database/commands.rs, apps/desktop/src-tauri/src/database/services/mutation.rs, apps/desktop/src-tauri/tauri.conf.json
Change some command return types to RawValue; optimize mutation code to avoid cloning; update tauri dev command and bundle targets.
Monaco / editor
apps/desktop/src/monaco-workers.ts, apps/desktop/src/main.tsx, apps/desktop/vite.config.ts, apps/desktop/package.json, package.json
Add monaco-workers initialization and monaco-editor dependency; add rollup visualizer and manualChunks in Vite config; add related package entries.
Removed hooks/utilities
apps/desktop/src/hooks/use-github-release.ts, apps/desktop/src/hooks/use-horizontal-scroll.ts
Deleted GitHub release hook and horizontal scroll hook.
Dependency cleanup & packaging
apps/desktop/package.json, package.json
Removed numerous UI/form libraries from desktop deps; added visualizer and monaco-editor/glob and testing helpers.
Developer tooling & scripts
tools/audit-cleanup.sh, tools/clean-fix.sh, tools/cleanup-dependencies.sh, tools/scan-dependencies.ts, tools/scan-unused.ts, recap.md
Add scripts for audit/cleanup, dependency scanning, unused-file scanning, and debugging recap documentation.

Sequence Diagram(s)

sequenceDiagram
    participant UI as Client (UI)
    participant Mutation as useMutation (updateCell)
    participant Cache as React Query Cache
    participant API as Backend API

    UI->>Mutation: call updateCell(newValue)
    activate Mutation
    Mutation->>Cache: onMutate — snapshot previous tableData
    Mutation->>Cache: apply optimistic update to tableData
    Cache-->>UI: render optimistic state

    par network
        Mutation->>API: send mutation request
        alt success
            API-->>Mutation: success response
            Mutation->>Cache: onSettled — invalidate tableData
            Cache->>API: refetch tableData
            API-->>Cache: new data
            Cache-->>UI: render confirmed state
        else error
            API-->>Mutation: error
            Mutation->>Cache: onError — restore snapshot
            Cache-->>UI: revert to previous state
        end
    end
    deactivate Mutation
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested labels

codex

Poem

🐰 I hopped through code with careful paws,
Removed some panels and tuned the laws,
Monaco workers hum and queries race,
Night theme settles, tidy workspace,
Scripts and fixes—clean build, applause! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the three main performance-focused changes: IPC layer optimization, bundle splitting, and Monaco worker offloading.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @remcostoeten, your pull request is larger than the review limit of 150000 diff characters

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
apps/desktop/src-tauri/src/database/commands.rs (1)

244-255: Type annotation mismatch between backend and frontend bindings for fetch_page.

The backend correctly returns Option<Box<serde_json::value::RawValue>> for efficient IPC pass-through. However, the auto-generated frontend type annotation declares the return as JsonValue | null, which is incompatible. RawValue serializes as raw JSON text, not as a parsed JsonValue object. The frontend bindings appear out of sync with the Rust type changes—regenerate bindings using tauri-specta to correct the TypeScript type annotation, or update it manually to reflect that the actual return value is a raw JSON string representation.

__tests__/apps/desktop/src/features/docker-manager/api/docker-client.test.ts (1)

11-49: Replace any with explicit Vitest mock types.

Using any erodes type safety. Per coding guidelines, prefer explicit types over any. For Vitest 4, use Mock<FunctionType> from vitest instead of ReturnType<typeof vi.fn>:

♻️ Suggested typing cleanup
+	import { type Mock } from 'vitest'
+
-	let mockExecute: any
-	let mockCreate: any
+	let mockExecute: Mock<() => Promise<{ stdout: string; stderr: string; code: number }>>
+	let mockCreate: Mock<(cmd: string, args: string[]) => void>

 	beforeEach(() => {
 		vi.clearAllMocks()
 		mockExecute = vi.fn().mockResolvedValue({ stdout: '', stderr: '', code: 0 })
 		mockCreate = vi.fn()

 		// Inject mock
-		deps.getCommand = async () => ({
+		type CommandCtor = typeof import('@tauri-apps/plugin-shell').Command
+		deps.getCommand = async () =>
+			({
 			create: (cmd: string, args: string[]) => {
 				mockCreate(cmd, args)
 				return {
 					execute: mockExecute,
 					on: vi.fn(),
 					spawn: vi.fn().mockResolvedValue({ kill: vi.fn() }),
 					stdout: { on: vi.fn() },
 					stderr: { on: vi.fn() }
 				}
 			}
-		} as any)
+		} as unknown as CommandCtor)
apps/desktop/src/shared/lib/appearance-store.ts (1)

23-56: Migrate legacy haptic theme to night.

If localStorage still contains haptic, the old class persists and the UI may lose theme styling. Map hapticnight on load and remove the legacy class from the DOM.

🔧 Proposed fix
 export function getAppearanceSettings(): AppearanceSettings {
 	try {
 		const stored = localStorage.getItem(STORAGE_KEY)
 		if (stored) {
 			// Merge with defaults to handle removal of density or new fields
 			const parsed = JSON.parse(stored)
+			if (parsed.theme === 'haptic') parsed.theme = 'night'
 			// Remove legacy density if present
 			delete parsed.density
 			return { ...DEFAULT_SETTINGS, ...parsed }
 		}
 	} catch (e) {
 		console.warn('Failed to load appearance settings:', e)
 	}
 	return DEFAULT_SETTINGS
 }
@@
 	// Theme
-	root.classList.remove('light', 'dark', 'midnight', 'forest', 'claude', 'claude-dark', 'night')
+	root.classList.remove('light', 'dark', 'midnight', 'forest', 'claude', 'claude-dark', 'night', 'haptic')
 	root.classList.add(settings.theme)
🤖 Fix all issues with AI agents
In @.github/workflows/release.yml:
- Around line 69-70: The workflow step "install rust stable" currently uses an
invalid action reference "dtolnay/rust-action@stable"; update this step's uses
value to the correct, valid action reference consistent with the Linux job fix
(replace the "uses: dtolnay/rust-action@stable" entry with the same working
reference used in the other job), ensuring the step name "install rust stable"
and the uses entry are updated together so the workflow picks the valid action.
- Around line 108-109: The "install rust stable" step is using an invalid action
reference (uses: dtolnay/rust-action@stable); update that step to use the same
correct action reference used in the Linux job (replace the
dtolnay/rust-action@stable value with the validated action identifier used
elsewhere in this workflow), keeping the step name "install rust stable" and
ensuring the action version/tag matches the Linux job's working configuration.
- Around line 25-26: The workflow uses an invalid GitHub Action identifier
"dtolnay/rust-action@stable" which will fail; update the step that currently
says uses: dtolnay/rust-action@stable to use the correct action identifier uses:
dtolnay/rust-toolchain@stable so the "install rust stable" step uses the proper
dtolnay/rust-toolchain action.
- Around line 28-31: Update the Ubuntu install step "install dependencies
(ubuntu)" to use the Tauri v2-required packages: replace libwebkit2gtk-4.0-dev
with libwebkit2gtk-4.1-dev and replace libappindicator3-dev with
libayatana-appindicator3-dev in the apt-get install list so the workflow matches
Tauri v2 prerequisites.
- Around line 119-133: Add the missing APPLE_TEAM_ID environment variable to the
tauri-action@v0 step so macOS notarization can use Apple ID-based notarization;
update the env block that already contains APPLE_ID and APPLE_PASSWORD to
include APPLE_TEAM_ID (reference the tauri-action@v0 step and the env variables
APPLE_ID and APPLE_PASSWORD) so the action receives APPLE_TEAM_ID from secrets
for notarization.
- Around line 41-50: The workflow uses the loose tauri-action@v0 and runs
release jobs in parallel causing race conditions; update the action reference in
the step that currently says "uses: tauri-apps/tauri-action@v0" to the pinned
"tauri-apps/tauri-action@v0.6.1" and serialize the release jobs by adding job
dependencies so the Windows and macOS release jobs (e.g., job ids like
release-windows and release-macos) include "needs: release-linux" (or whatever
the Linux release job id is) so only the Linux job creates/updates the GitHub
release first.

In `@apps/desktop/src/core/data-provider/hooks.ts`:
- Line 1: Replace the use of `any` in the optimistic updater with a concrete
response type: define a `TableDataResponse` interface/type that matches the API
shape (including `rows: Array<...>` and any other fields) and then change the
`queryClient.setQueriesData` updater signature to use that type instead of `any`
(the call site is the optimistic update using `queryClient.setQueriesData({
queryKey: ['tableData', newEdit.connectionId, newEdit.tableName] }, (old: any)
=> { ... })`); ensure the updater handles `old` possibly being undefined (narrow
or default it) and update usages inside the updater to rely on the typed
`old.rows` so TypeScript enforces correctness.

In `@apps/desktop/src/features/drizzle-runner/components/lsp-demo-widget.tsx`:
- Around line 238-252: The auto-close effect handleSuccessAutoClose should only
perform the 2s auto-close and countdown when an onClose callback is provided;
update the useEffect so it checks that isSuccess && typeof onClose ===
"function" before setting the timer, and only call onClose and clear/set
IsSuccess inside that guarded branch (keep the cleanup to clear timer). Apply
the same guard to the other similar effect/logic that shows the "Closing in 2
seconds..." countdown and auto-clears success (the second effect around the
countdown), ensuring the message is only shown when onClose exists.
- Around line 115-117: The declared state setter setDemos is unused and triggers
eslint no-unused-vars; either remove the setter from the useState call or rename
it to _setDemos to silence the linter. Update the hook declaration that
currently reads useState<DemoQuery[]>(DEFAULT_DEMOS) so it only keeps the needed
symbols (e.g., keep demos and remove setDemos) or rename setDemos to _setDemos;
make this change where demos, setDemos, DEFAULT_DEMOS and useState are
referenced so future edits can restore the setter if needed.

In `@tools/scan-dependencies.ts`:
- Line 14: The arrow function readFile should be converted to a function
declaration to satisfy ESLint; replace the const readFile = (p: string) => ...
with a function declaration function readFile(p: string): string { ... }
preserving the exact behavior (check fs.existsSync(p) and return
fs.readFileSync(p, 'utf-8') or ''), keeping the same function name and parameter
to avoid changing callers.
🧹 Nitpick comments (15)
__tests__/apps/desktop/features/drizzle-runner/lsp-patterns.test.ts (1)

14-14: Consider using a path alias instead of a deep relative import.

The 6-level relative path (../../../../../) is brittle and makes the test fragile to directory structure changes. Using a path alias would improve maintainability.

♻️ Suggested refactor using path alias
-} from '../../../../../apps/desktop/src/features/drizzle-runner/utils/lsp-patterns'
+} from '@/apps/desktop/src/features/drizzle-runner/utils/lsp-patterns'

Note: Ensure your tsconfig paths or vitest config includes an alias mapping for @/ pointing to the project root or appropriate base path.

.github/workflows/release.yml (1)

7-51: Consider adding dependency caching for faster CI builds.

The workflow installs Bun packages and Rust dependencies from scratch on every run. Adding caching can significantly reduce build times.

♻️ Example cache configuration for the Linux job
       - name: setup bun
         uses: oven-sh/setup-bun@v2
         with:
             bun-version: latest

+      - name: cache cargo
+        uses: actions/cache@v4
+        with:
+          path: |
+            ~/.cargo/bin/
+            ~/.cargo/registry/index/
+            ~/.cargo/registry/cache/
+            ~/.cargo/git/db/
+            apps/desktop/src-tauri/target/
+          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+
       - name: install rust stable
         uses: dtolnay/rust-toolchain@stable
apps/desktop/src/features/drizzle-runner/components/lsp-demo-widget.tsx (1)

340-366: Prefer shared Button component and explicit props typing.

This inline Button duplicates the shared UI primitive and uses any. Consider importing the shared Button from @/shared/components/ui and extending its variants (e.g., adding success) there. This keeps styling consistent and aligns with the TS typing guideline. As per coding guidelines, prefer shared UI primitives and avoid any.

apps/desktop/src/core/data-provider/hooks.ts (1)

192-204: Use the existing TableData type instead of any.

The codebase already defines a TableData type in @/features/database-studio/types.ts with the structure { columns: ColumnDefinition[], rows: Record<string, unknown>[], totalCount: number, executionTime: number }. Import and use this type for the optimistic update instead of any.

♻️ Suggested typing update
+import type { TableData } from '@/features/database-studio/types'
+
-			queryClient.setQueriesData({ queryKey: ['tableData', newEdit.connectionId, newEdit.tableName] }, (old: any) => {
+			queryClient.setQueriesData<TableData>(
+				{ queryKey: ['tableData', newEdit.connectionId, newEdit.tableName] },
+				(old) => {
-				if (!old) return old
+					if (!old?.rows) return old
-				return {
-					...old,
-					rows: old.rows.map((row: any) => {
+					return {
+						...old,
+						rows: old.rows.map((row) => {
-						if (row[newEdit.primaryKeyColumn] === newEdit.primaryKeyValue) {
-							return {
-								...row,
-								[newEdit.columnName]: newEdit.newValue
-							}
-						}
-						return row
-					})
-				}
-			})
+							if (row[newEdit.primaryKeyColumn] === newEdit.primaryKeyValue) {
+								return {
+									...row,
+									[newEdit.columnName]: newEdit.newValue
+								}
+							}
+							return row
+						})
+					}
+				}
+			)
package.json (1)

46-47: Consider pinning React versions consistently.

react and react-dom are pinned at 18.3.1 without the ^ prefix, which is good for deterministic builds. Ensure these versions match what's used in apps/desktop/package.json to avoid version mismatches in the monorepo.

tools/clean-fix.sh (2)

4-5: Consider using script directory instead of pwd.

Using pwd makes the script dependent on the caller's working directory. Deriving the root from the script's location is more robust.

Suggested improvement
-# Define root directory
-ROOT_DIR=$(pwd)
+# Define root directory relative to script location
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"

12-13: Add existence checks for safety.

If apps or packages directories don't exist, find will error. Consider adding guards or using -maxdepth 0 checks.

Suggested improvement
 # Find and remove items in subdirectories
-find "$ROOT_DIR/apps" "$ROOT_DIR/packages" -type d \( -name "node_modules" -o -name ".next" -o -name ".turbo" -o -name "dist" -o -name ".vite" \) -prune -exec rm -rf {} +
+for dir in "$ROOT_DIR/apps" "$ROOT_DIR/packages"; do
+  if [ -d "$dir" ]; then
+    find "$dir" -type d \( -name "node_modules" -o -name ".next" -o -name ".turbo" -o -name "dist" -o -name ".vite" \) -prune -exec rm -rf {} +
+  fi
+done
apps/desktop/src/features/sidebar/components/bottom-toolbar.tsx (1)

1-13: Avoid Theme type drift by importing the shared Theme type.

Theme already exists in apps/desktop/src/shared/lib/appearance-store.ts; reusing it prevents future mismatches.

♻️ Suggested change
 import { Settings, Monitor, Sparkles, Info } from 'lucide-react'
+import type { Theme } from '@/shared/lib/appearance-store'
@@
-type Theme = 'dark' | 'light' | 'midnight' | 'forest' | 'claude' | 'claude-dark' | 'night'
__tests__/apps/desktop/src/features/docker-manager/api/container-service.test.ts (1)

13-16: Avoid any for dynamically imported modules.

Use typeof import(...) to keep the module API typed and refactor-safe.

🔧 Proposed fix
-	let containerService: any;
-	let dockerClient: any;
+	type DockerClientModule = typeof import('../../../../../../../apps/desktop/src/features/docker-manager/api/docker-client')
+	type ContainerServiceModule = typeof import('../../../../../../../apps/desktop/src/features/docker-manager/api/container-service')
+	let containerService: ContainerServiceModule;
+	let dockerClient: DockerClientModule;

As per coding guidelines, prefer explicit types over any.

__tests__/apps/desktop/src/features/docker-manager/components/docker-view.test.tsx (1)

6-6: Use the shared UI index for TooltipProvider.

Shared UI primitives should be imported from @/shared/components/ui; update the TooltipProvider import accordingly (or re-export it there).

🔧 Proposed fix
-import { TooltipProvider } from '@/shared/ui/tooltip'
+import { TooltipProvider } from '@/shared/components/ui'

As per coding guidelines, import shared UI primitives from @/shared/components/ui.

tools/audit-cleanup.sh (1)

7-9: Anchor PROJECT_ROOT to the script location.

Using pwd makes behavior depend on the caller’s CWD; in execute mode this can delete the wrong paths or run bun run build outside the repo. Resolve the repo root relative to the script instead.

🔧 Proposed fix
-BACKUP_ROOT="$HOME/.dora/backups/$(date +%Y%m%d_%H%M%S)"
-PROJECT_ROOT=$(pwd)
+BACKUP_ROOT="$HOME/.dora/backups/$(date +%Y%m%d_%H%M%S)"
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
tools/scan-dependencies.ts (1)

77-103: Substring matching may yield false positives for short package names.

The heuristic allContent.includes(dep) can match unrelated occurrences. For example, is would match any word containing "is". Consider using a regex with word boundaries for more accurate detection, especially for short package names.

Suggested improvement
-        const isUsed = allContent.includes(dep) || (isTypes && allContent.includes(searchName));
+        // Use word boundary check for more accurate matching
+        const depPattern = new RegExp(`['"\`/]${dep.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}['"\`/]|from\\s+['"]${dep.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`)
+        const searchPattern = isTypes ? new RegExp(`['"\`]${searchName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}['"\`]`) : null
+        const isUsed = depPattern.test(allContent) || (isTypes && searchPattern?.test(allContent));
recap.md (1)

8-12: Minor: Consider varying sentence structure.

Three consecutive bullet points start with "Tried". Consider rephrasing for better readability (e.g., "Added debug logs...", "Experimented with...", "Created a global...").

apps/desktop/src/features/sidebar/database-sidebar.tsx (1)

681-689: Consider adding keyboard accessibility for the resizer.

The resizer handle only responds to mouse events. For accessibility, consider adding keyboard support (e.g., arrow keys to adjust the ratio when focused).

Example keyboard support
 <div
+    tabIndex={0}
+    role="separator"
+    aria-orientation="horizontal"
+    aria-valuenow={Math.round(topPanelRatio * 100)}
     className='h-1.5 shrink-0 bg-sidebar-border/30 hover:bg-primary/20 cursor-row-resize flex items-center justify-center transition-colors z-20 -my-0.5'
     onMouseDown={(e) => {
         e.preventDefault()
         setIsResizing(true)
     }}
+    onKeyDown={(e) => {
+        if (e.key === 'ArrowUp') {
+            setTopPanelRatio(r => Math.max(0.2, r - 0.05))
+        } else if (e.key === 'ArrowDown') {
+            setTopPanelRatio(r => Math.min(0.85, r + 0.05))
+        }
+    }}
 >
apps/desktop/src/monaco-workers.ts (1)

8-24: Replace any with explicit type.

Per coding guidelines, prefer explicit types over any. The first parameter is the module ID (string).

Proposed fix
 self.MonacoEnvironment = {
-    getWorker(_: any, label: string) {
+    getWorker(_moduleId: string, label: string) {
         if (label === 'json') {

Comment on lines +28 to +31
- name: install dependencies (ubuntu)
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check Tauri version in Cargo.toml
fd -t f 'Cargo.toml' -x grep -H 'tauri' {} \;

Repository: remcostoeten/dora

Length of output: 478


🌐 Web query:

Tauri v2 Linux dependencies libwebkit2gtk libappindicator official documentation

💡 Result:

In Tauri v2, the official docs list these Linux packages relevant to your question:

  • Development (build) dependencies (Debian/Ubuntu example):

    • libwebkit2gtk-4.1-dev (WebView / WebKit2GTK)
    • libayatana-appindicator3-dev (AppIndicator/system tray support; Tauri v2 uses Ayatana on many distros) (v2.tauri.app)
  • Runtime (shipping) dependencies for Debian-based .deb packages:

    • libwebkit2gtk-4.1-0
    • libgtk-3-0
    • libappindicator3-1 only if your app uses the system tray (v2.tauri.app)

If you specifically meant libappindicator vs libayatana-appindicator: Tauri v2’s prerequisites page uses Ayatana (libayatana-appindicator3-dev) for the Linux dev setup example. (v2.tauri.app)

Citations:


Update Linux dependencies for Tauri v2.

The workflow is using Tauri v2.8.0 but has outdated dependencies. For Tauri v2, replace:

  • libwebkit2gtk-4.0-devlibwebkit2gtk-4.1-dev
  • libappindicator3-devlibayatana-appindicator3-dev

This aligns with the official Tauri v2 prerequisites.

🤖 Prompt for AI Agents
In @.github/workflows/release.yml around lines 28 - 31, Update the Ubuntu
install step "install dependencies (ubuntu)" to use the Tauri v2-required
packages: replace libwebkit2gtk-4.0-dev with libwebkit2gtk-4.1-dev and replace
libappindicator3-dev with libayatana-appindicator3-dev in the apt-get install
list so the workflow matches Tauri v2 prerequisites.

Comment on lines +41 to +50
- uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
projectPath: ./apps/desktop
tagName: ${{ github.ref_name }}
releaseName: 'App v__VERSION__'
releaseBody: 'See the assets to download this version and install.'
releaseDraft: true
prerelease: false
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

latest stable version tauri-apps/tauri-action GitHub Action

💡 Result:

Latest stable release of tauri-apps/tauri-action is v0.6.1 (tag: action-v0.6.1, released 2026-01-03). [1]

You can pin it as:

- uses: tauri-apps/tauri-action@v0.6.1

Source: GitHub Releases page. [1]

[1] https://github.com/tauri-apps/tauri-action/releases


🏁 Script executed:

# Let's examine the release.yml workflow to understand the job structure
cat -n .github/workflows/release.yml

Repository: remcostoeten/dora

Length of output: 4572


Pin tauri-action to v0.6.1 and serialize release jobs to prevent race conditions.

  1. Using @v0 is very loose and could introduce breaking changes unexpectedly. Pin to the latest stable version: @v0.6.1.

  2. All three jobs run in parallel and each attempts to create/update the same GitHub release. This can cause race conditions. Consider making Windows and macOS jobs depend on the Linux job using needs: release-linux.

♻️ Proposed fix for job dependencies
   release-windows:
+    needs: release-linux
     permissions:
       contents: write
     runs-on: windows-latest
   release-macos:
+    needs: release-linux
     permissions:
       contents: write
     runs-on: macos-latest
🤖 Prompt for AI Agents
In @.github/workflows/release.yml around lines 41 - 50, The workflow uses the
loose tauri-action@v0 and runs release jobs in parallel causing race conditions;
update the action reference in the step that currently says "uses:
tauri-apps/tauri-action@v0" to the pinned "tauri-apps/tauri-action@v0.6.1" and
serialize the release jobs by adding job dependencies so the Windows and macOS
release jobs (e.g., job ids like release-windows and release-macos) include
"needs: release-linux" (or whatever the Linux release job id is) so only the
Linux job creates/updates the GitHub release first.

Comment on lines +119 to +133
- uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
with:
projectPath: ./apps/desktop
tagName: ${{ github.ref_name }}
releaseName: 'App v__VERSION__'
releaseBody: 'See the assets to download this version and install.'
releaseDraft: true
prerelease: false
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

tauri-apps tauri-action v0 macOS notarization APPLE_TEAM_ID environment variables

💡 Result:

For tauri-apps/tauri-action@v0 on macOS, notarization credentials are passed via environment variables (typically from GitHub Secrets). If you notarize using Apple ID + app-specific password, you should set all of these:

  • APPLE_ID (your Apple ID email)
  • APPLE_PASSWORD (app-specific password)
  • APPLE_TEAM_ID (your Apple Developer Team ID) — required when using Apple ID auth for notarization in current tooling/docs
  • (for signing) APPLE_CERTIFICATE (base64 .p12), APPLE_CERTIFICATE_PASSWORD, APPLE_SIGNING_IDENTITY (keychain identity name)

Example (as used with tauri-action@v0):

- uses: tauri-apps/tauri-action@v0
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
    APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
    APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
    APPLE_ID: ${{ secrets.APPLE_ID }}
    APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
    APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}

Sources: Tauri v1 signing guide (shows tauri-action@v0 + APPLE_TEAM_ID) [1], Tauri environment variables reference (states APPLE_TEAM_ID is required when APPLE_ID is provided) [2], and tauri-bundler release notes calling out APPLE_TEAM_ID being required for Apple ID notarization auth [3].

References
[1] https://v1.tauri.app/v1/guides/distribution/sign-macos/
[2] https://v2.tauri.app/reference/environment-variables/
[3] https://v2.tauri.app/release/tauri-bundler/v1.4.1/


Add missing APPLE_TEAM_ID environment variable for macOS notarization.

The workflow is missing APPLE_TEAM_ID, which is required for Apple ID-based notarization with tauri-action@v0. Without it, notarization will fail. Add:

APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}

to the environment variables alongside the existing APPLE_ID and APPLE_PASSWORD.

🤖 Prompt for AI Agents
In @.github/workflows/release.yml around lines 119 - 133, Add the missing
APPLE_TEAM_ID environment variable to the tauri-action@v0 step so macOS
notarization can use Apple ID-based notarization; update the env block that
already contains APPLE_ID and APPLE_PASSWORD to include APPLE_TEAM_ID (reference
the tauri-action@v0 step and the env variables APPLE_ID and APPLE_PASSWORD) so
the action receives APPLE_TEAM_ID from secrets for notarization.

@@ -1,4 +1,4 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useMutation, useQuery, useQueryClient, keepPreviousData } from '@tanstack/react-query'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check `@tanstack/react-query` version in manifests/lockfiles
rg -n '"@tanstack/react-query"' -g 'package.json' -g 'pnpm-lock.yaml' -g 'yarn.lock' -g 'package-lock.json' | head -20

Repository: remcostoeten/dora

Length of output: 205


🏁 Script executed:

#!/bin/bash
# Check the actual file content for the imports and usage
cat -n apps/desktop/src/core/data-provider/hooks.ts | head -50

Repository: remcostoeten/dora

Length of output: 1725


🏁 Script executed:

#!/bin/bash
# Read more of the file to see the changes around lines 141-144 and 184-224
cat -n apps/desktop/src/core/data-provider/hooks.ts | sed -n '130,250p'

Repository: remcostoeten/dora

Length of output: 4158


🌐 Web query:

keepPreviousData React Query v5.83.0 API

💡 Result:

In TanStack React Query v5.83.0, there is no keepPreviousData: true option anymore. It was removed in v5 in favor of placeholderData (and the flag isPlaceholderData instead of isPreviousData). (tanstack.com)

Equivalent v5 API

Option form (identity function):

useQuery({
  queryKey,
  queryFn,
  placeholderData: (previousData) => previousData,
})

(tanstack.com)

Using the built-in helper (recommended):

import { useQuery, keepPreviousData } from '@tanstack/react-query'

useQuery({
  queryKey,
  queryFn,
  placeholderData: keepPreviousData,
})

(tanstack.com)

Flag replacement:

Citations:


Use explicit type instead of any for the optimistic updater parameter.

The keepPreviousData import is available in React Query v5.83.0 and correctly used. However, the optimistic updater at line 192 should not use any for the cached data parameter:

queryClient.setQueriesData({ queryKey: ['tableData', newEdit.connectionId, newEdit.tableName] }, (old: TableDataResponse) => {

Define TableDataResponse type to match your API response structure (with rows array) and use it instead of any to maintain type safety throughout the optimistic update.

🤖 Prompt for AI Agents
In `@apps/desktop/src/core/data-provider/hooks.ts` at line 1, Replace the use of
`any` in the optimistic updater with a concrete response type: define a
`TableDataResponse` interface/type that matches the API shape (including `rows:
Array<...>` and any other fields) and then change the
`queryClient.setQueriesData` updater signature to use that type instead of `any`
(the call site is the optimistic update using `queryClient.setQueriesData({
queryKey: ['tableData', newEdit.connectionId, newEdit.tableName] }, (old: any)
=> { ... })`); ensure the updater handles `old` possibly being undefined (narrow
or default it) and update usages inside the updater to rely on the typed
`old.rows` so TypeScript enforces correctness.

Comment on lines +115 to 117
// ... existing state ...
const [isSuccess, setIsSuccess] = useState(false)
const [demos, setDemos] = useState<DemoQuery[]>(DEFAULT_DEMOS)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix unused setDemos to clear the CI warning.

CI shows setDemos is unused (eslint no-unused-vars). Remove it or rename to _setDemos if you intend to keep it around.

🧹 Proposed fix
- const [demos, setDemos] = useState<DemoQuery[]>(DEFAULT_DEMOS)
+ const [demos] = useState<DemoQuery[]>(DEFAULT_DEMOS)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// ... existing state ...
const [isSuccess, setIsSuccess] = useState(false)
const [demos, setDemos] = useState<DemoQuery[]>(DEFAULT_DEMOS)
// ... existing state ...
const [isSuccess, setIsSuccess] = useState(false)
const [demos] = useState<DemoQuery[]>(DEFAULT_DEMOS)
🧰 Tools
🪛 GitHub Actions: CI

[warning] 117-117: eslint(no-unused-vars): Variable 'setDemos' is declared but never used. Unused variables should start with a '_'.

🤖 Prompt for AI Agents
In `@apps/desktop/src/features/drizzle-runner/components/lsp-demo-widget.tsx`
around lines 115 - 117, The declared state setter setDemos is unused and
triggers eslint no-unused-vars; either remove the setter from the useState call
or rename it to _setDemos to silence the linter. Update the hook declaration
that currently reads useState<DemoQuery[]>(DEFAULT_DEMOS) so it only keeps the
needed symbols (e.g., keep demos and remove setDemos) or rename setDemos to
_setDemos; make this change where demos, setDemos, DEFAULT_DEMOS and useState
are referenced so future edits can restore the setter if needed.

Comment on lines +238 to +252
// Auto-close on success
useEffect(
function handleSuccessAutoClose() {
if (isSuccess) {
const timer = setTimeout(function closeWidget() {
setIsSuccess(false)
if (onClose) onClose()
}, 2000)
return function cleanup() {
clearTimeout(timer)
}
}
},
[isSuccess, onClose]
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Guard auto-close + countdown copy when onClose is absent.

Right now the “Closing in 2 seconds...” message appears even when onClose isn’t provided, and the effect still clears success after 2s. That reads like a close that never happens. Consider only auto-closing (and showing the countdown) when onClose exists.

✅ Suggested adjustment
- useEffect(
-  function handleSuccessAutoClose() {
-    if (isSuccess) {
-      const timer = setTimeout(function closeWidget() {
-        setIsSuccess(false)
-        if (onClose) onClose()
-      }, 2000)
-      return function cleanup() {
-        clearTimeout(timer)
-      }
-    }
-  },
-  [isSuccess, onClose]
- )
+ useEffect(
+  function handleSuccessAutoClose() {
+    if (isSuccess && onClose) {
+      const timer = setTimeout(function closeWidget() {
+        setIsSuccess(false)
+        onClose()
+      }, 2000)
+      return function cleanup() {
+        clearTimeout(timer)
+      }
+    }
+  },
+  [isSuccess, onClose]
+ )
- <span className='text-xs text-muted-foreground font-normal'>
-   Closing in 2 seconds...
- </span>
+ {onClose ? (
+   <span className='text-xs text-muted-foreground font-normal'>
+     Closing in 2 seconds...
+   </span>
+ ) : (
+   <span className='text-xs text-muted-foreground font-normal'>
+     You can close this window when you’re done.
+   </span>
+ )}

Also applies to: 398-409

🤖 Prompt for AI Agents
In `@apps/desktop/src/features/drizzle-runner/components/lsp-demo-widget.tsx`
around lines 238 - 252, The auto-close effect handleSuccessAutoClose should only
perform the 2s auto-close and countdown when an onClose callback is provided;
update the useEffect so it checks that isSuccess && typeof onClose ===
"function" before setting the timer, and only call onClose and clear/set
IsSuccess inside that guarded branch (keep the cleanup to clear timer). Apply
the same guard to the other similar effect/logic that shows the "Closing in 2
seconds..." countdown and auto-clears success (the second effect around the
countdown), ensuring the message is only shown when onClose exists.

remcostoeten and others added 4 commits January 26, 2026 05:07
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Remco <remcostoeten@hotmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Remco <remcostoeten@hotmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Remco <remcostoeten@hotmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Remco <remcostoeten@hotmail.com>
@remcostoeten remcostoeten merged commit 373348e into master Jan 26, 2026
7 of 9 checks passed
@remcostoeten remcostoeten deleted the feature/performance-optimizations branch January 26, 2026 04:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant